﻿@typeparam TItem
@using System.Collections

@switch (LoadingStatus)
{
    case LoadingStatus.NotLoaded:
        @NotLoadedContent
        break;

    case LoadingStatus.Loading:
        @LoadingContent
        break;

    case LoadingStatus.Loaded:
        if (Data == null || (Data != null && IsGenericList && (Data as IList).Count == 0))
        {
            @NoResultsContent
        }
        else
        {
            @LoadedContent(Data)
        }
        break;

    case LoadingStatus.Failed:
        @FailedContent
        break;
}


@code
{
    #region Public Properties

    /// <summary>
    /// The information you will be binding this control against. You should typically use the two-way binding syntax of '@bind-Data' to connect this 
    /// information to the control.
    /// </summary>
    [Parameter]
    public TItem Data { get; set; }

    /// <summary>
    /// The event handler used to update the Parent control about <see cref="Data"/> changes during two-way binding.
    /// </summary>
    [Parameter]
    public EventCallback<TItem> DataChanged { get; set; }

    /// <summary>
    ///The content to display when the <see cref="LoadingStatus"/> list set to <see cref="LoadingStatus.Failed"/>.
    /// </summary>
    [Parameter]
    public RenderFragment FailedContent { get; set; }

    /// <summary>
    ///The content to display when the <see cref="LoadingStatus"/> list set to <see cref="LoadingStatus.Loaded"/>.
    /// </summary>
    [Parameter]
    public RenderFragment<TItem> LoadedContent { get; set; }

    /// <summary>
    ///The content to display when the <see cref="LoadingStatus"/> list set to <see cref="LoadingStatus.Loading"/>.
    /// </summary>
    [Parameter]
    public RenderFragment LoadingContent { get; set; }

    /// <summary>
    /// The particular property containing the LoadingStatus that you want to track.. You should typically use the two-way binding syntax of '@bind-Data' to 
    /// connect this information to the control.
    /// </summary>
    [Parameter]
    public LoadingStatus LoadingStatus { get; set; }

    /// <summary>
    /// The event handler used to update the Parent control about <see cref="LoadingStatus"/> changes during two-way binding.
    /// </summary>
    [Parameter]
    public EventCallback<LoadingStatus> LoadingStatusChanged { get; set; }

    /// <summary>
    ///The content to display when the <see cref="LoadingStatus"/> list set to <see cref="LoadingStatus.Loaded"/> and <see cref="Data"/> list either null, 
    ///or is a list that contains no objects.
    /// </summary>
    [Parameter]
    public RenderFragment NoResultsContent { get; set; }

    /// <summary>
    ///The content to display when the <see cref="LoadingStatus"/> list set to <see cref="LoadingStatus.NotLoaded"/>. This is typically the initial state 
    ///for a ViewModel.
    /// </summary>
    [Parameter]
    public RenderFragment NotLoadedContent { get; set; }

        #endregion

    #region Private Properties

    /// <summary>
    /// Used to determine whether the <see cref="Data"/> property is a single object or a <see cref="List{T}" /> of objects.
    /// </summary>
    private bool IsGenericList
    {
        get
        {
            var type = typeof(TItem);
            var interfaceTest = new Predicate<Type>(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>));
            return interfaceTest(type) || type.GetInterfaces().Any(i => interfaceTest(i));
        }
    }

    #endregion

}